package com.ldzy.webase.service.impl;

import com.ldzy.webase.dao.UserMapper;
import com.ldzy.webase.entity.Comment;
import com.ldzy.webase.entity.Press;
import com.ldzy.webase.entity.User;
import com.ldzy.webase.exception.ExceptionResponse;
import com.ldzy.webase.exception.ExceptionResponseCode;
import com.ldzy.webase.service.UserService;
import com.ldzy.webase.utils.TokenUtil;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

/**
 * @author ：Lq
 * @version ：1.0
 * @date ：2022/10/25 12:07
 * @description ：用户-业务实现层
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TokenUtil tokenUtil;

    /**
     * @author ：Lq
     * @date ：2022/10/22 15:14
     * @description ：登陆，成功返回则 token
     */
    @Override
    public String loginByStudentIdOrPhoneNumber(User user) throws ExceptionResponse {
        User user1 = userMapper.loginByStudentIdOrPhoneNumber(user);

        // 数据库无此用户
        if (user1 == null) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_USERNAME_OR_PASSWORD); // (401, "用户名或密码错误，请重新登陆")
        }

        return tokenUtil.getToken(user1);
    }

    /**
     * @author ：Lq
     * @date ：2022/10/25 12:07
     * @description ：注册
     */
    // 注册 (成功返回1，否则返回0)
    public int register(User user) {
        // 注册时提前查询学号是否被占用
        User userInfoByStudentId = userMapper.getUserInfoByStudentId(user.getStudentId());
        if (userInfoByStudentId != null) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_UNIQUE_STUDENTID); // (401, "注册失败，学号已被占用，如果不是本人操作请联系管理员")
        }

        // 注册时提前查询手机号是否被占用
        User userInfoByPhoneNumber = userMapper.getUserInfoByPhoneNumber(user.getPhoneNumber());
        if (userInfoByPhoneNumber != null) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_UNIQUE_PHONENUMBER); // (401, "注册失败，手机号已被占用，如果不是本人操作请联系管理员")
        }

        // 有两个唯一约束条件 【学号、手机号】，会抛出异常
        int i = userMapper.register(user);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_REGISTER); // (401, "注册失败，预期外的错误")
        }

        return i;
    }

    /**
     * @author ：Lq
     * @date ：2022/10/24 11:14
     * @description ：根据用户uid查询密码并返回
     */
    @Override
    public String getPasswordByUid(Integer uid) {
        String passwordByUid = userMapper.getPasswordByUid(uid);

        return passwordByUid;
    }

    /**
     * @author ：Lq
     * @date ：2022/10/24 11:16
     * @description ：根据用户uid查询用户最后登陆时间
     */
    @Override
    public Timestamp getEndLoginTimeByUid(Integer uid) {
        Timestamp endLoginTimeByUid = userMapper.getEndLoginTimeByUid(uid);

        if (endLoginTimeByUid == null) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_TOKEN);
        }

        return endLoginTimeByUid;
    }

    /**
     * @author ：Lq
     * @date ：2022/10/24 11:17
     * @description ：根据用户uid修改用户最后登陆时间
     */
    @Override
    public int editEndLoginTimeByUid(String endLoginTime, Integer uid) {
        int i = userMapper.editEndLoginTimeByUid(endLoginTime, uid);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_TOKEN);
        }

        return i;
    }

    /**
     * @author ：Lq
     * @date ：2022/10/24 11:17
     * @description ：根据uid获取用户基本信息
     */
    @Override
    public User getUserInfoByUid(Integer uid) {
        User userInfo = userMapper.getUserInfo(uid);

        // 数据库无此用户
        if (userInfo == null) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_USER);// (401, "用户不存在，请重新登录")
        }

        return userInfo;
    }

    /**
     * @author ：Lq
     * @date ：2022/10/25 12:07
     * @description ：根据uid修改用户基本信息
     */
    @Override
    public int editUserInfoByUid(User user) {
        int i = userMapper.editUserInfoByUid(user);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_TOKEN); // (401, "服务器开小差了")
        }

        return i;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/9 14:08
     * @description ：查询用户所有已发布的咨询
     */
    @Override
    public List<Press> getPressByUid(Integer uid) {
        List<Press> pressList = userMapper.getPressByUid(uid);

        // 循环遍历查询出来的咨询/话题，格式化图片路径
        for (int i = 0; i < pressList.size(); i++) {
            // 取出图片路径
            String pressImages = pressList.get(i).getPressImages();

            // 判断不为空
            if (pressImages != null && !pressImages.equals("")) {
                // 利用split进行分隔为数组
                String[] strList = pressImages.split(";");

                //保留数组格式输出
//                System.out.println(JSONUtil.toJsonStr(strList));

                // 将分割后的图片路径存入
                pressList.get(i).setPressImagesList(strList);
            }

            // 取出发布日期
            Timestamp publishDate = pressList.get(i).getPublishDate();
            // 获取当前时间
            Date nowDate = new Date();
            // 计算发布日期距离当前时间过去了多久，获取计算后的时间戳（单位：毫秒数）
            long times = nowDate.getTime() - publishDate.getTime();
            long day = times / (24 * 60 * 60 * 1000); // 天数
            long hour = (times / (60 * 60 * 1000) - day * 24); // 小时
            long min = ((times / (60 * 1000)) - day * 24 * 60 - hour * 60); // 分钟
            long sec = (times / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); // 秒

            // 创建可变字符缓冲对象StringBuffer，只是为了方便
            StringBuffer sb = new StringBuffer();

            if (day > 7) {
                // 如果大于7天不执行操作
            } else if (day > 0) {
                sb.append(day + "天前");
            } else if (hour > 0) {
                sb.append(hour + "小时前");
            } else if (min > 0) {
                sb.append(min + "分钟前");
            } else if (sec < 10) {
                sb.append("刚刚");
            } else {
                sb.append(sec + "秒前");
            }

            // sb.toString()转换成字符串对象存入
            pressList.get(i).setPublishDateInterval(sb.toString());
        }

        return pressList;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/16 17:12
     * @description ：查询用户所有已发表的评论
     */
    @Override
    public List<Comment> getCommentByUid(Integer uid) {
        List<Comment> commentList = userMapper.getCommentByUid(uid);

        // 循环遍历查询出来的评论，格式化图片路径
        for (int i = 0; i < commentList.size(); i++) {
            // 取出评论图片路径
            String contentImages = commentList.get(i).getContentImages();
            // 取出话题图片路径
            String pressImages = commentList.get(i).getPressImages();

            // 判断不为空
            if (contentImages != null && !contentImages.equals("")) {
                // 利用split进行分隔为数组
                String[] strList = contentImages.split(";");

                //保留数组格式输出
//                System.out.println(JSONUtil.toJsonStr(strList));

                // 将分割后的图片路径存入
                commentList.get(i).setCommentImagesList(strList);
            }

            // 判断不为空
            if (pressImages != null && !pressImages.equals("")) {
                // 利用split进行分隔为数组
                String[] strList = pressImages.split(";");

                //保留数组格式输出
//                System.out.println(JSONUtil.toJsonStr(strList));

                // 将分割后的图片路径存入-如果有很多种，只取话题的第一张，只用作预览
                commentList.get(i).setPressImages(strList[0]);
            }

            // 取出发布日期
            Timestamp commentDate = commentList.get(i).getCommentDate();
            // 获取当前时间
            Date nowDate = new Date();
            // 计算发布日期距离当前时间过去了多久，获取计算后的时间戳（单位：毫秒数）
            long times = nowDate.getTime() - commentDate.getTime();
            long day = times / (24 * 60 * 60 * 1000); // 天数
            long hour = (times / (60 * 60 * 1000) - day * 24); // 小时
            long min = ((times / (60 * 1000)) - day * 24 * 60 - hour * 60); // 分钟
            long sec = (times / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); // 秒

            // 创建可变字符缓冲对象StringBuffer，只是为了方便
            StringBuffer sb = new StringBuffer();

            if (day > 7) {
                // 如果大于7天不执行操作
            } else if (day > 0) {
                sb.append(day + "天前");
            } else if (hour > 0) {
                sb.append(hour + "小时前");
            } else if (min > 0) {
                sb.append(min + "分钟前");
            } else if (sec < 10) {
                sb.append("刚刚");
            } else {
                sb.append(sec + "秒前");
            }

            // sb.toString()转换成字符串对象存入
            commentList.get(i).setCommentDateInterval(sb.toString());
        }

        return commentList;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/9 14:09
     * @description ：根据咨询pressId和用户uid，删除对应的咨询表t_press中的数据，删除对应的评论表，删除对应的咨询点赞表
     */
    @Override
    public int delPressByPressIdAndUid(Integer pressId, Integer uid) {
        int i = userMapper.delPressByPressIdAndUid(pressId, uid);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_DELETE_DATA); // (401, "删除失败，服务器开小差了")
        }

        return i;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/13 16:17
     * @description ：根据咨询pressId和用户uid，编辑对应的咨询表t_press中的数据
     */
    public int editPressByPressIdAndUid(Press press) {
        System.out.println(press);
        int i = userMapper.editPressByPressIdAndUid(press);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_EDIT_PRESS); // (401, "编辑失败，服务器开小差了")
        }

        return i;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/14 17:41
     * @description ：根据学生uid修改邮箱 (其一来源：uid来源于token)
     */
    @Override
    public int editUserEmailByUid(User user) {
        User userInfoByEmail = userMapper.getUserInfoByEmail(user.getEmail());
        if (userInfoByEmail != null) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_UNIQUE_EMAIL); // (401, "绑定邮箱失败，邮箱已被占用，如果不是本人操作请联系管理员")
        }

        int i = userMapper.editUserEmailByUid(user);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_TOKEN); // (401, "服务器开小差了")
        }

        return i;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/14 19:28
     * @description ：根据邮箱获取学生uid (其一来源：email来源于前端传参)
     */
    @Override
    public String getUidByEmail(String email) {
        String uid = userMapper.getUidByEmail(email);

        if (uid == null || uid.equals("")) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_TOKEN); // (401, "服务器开小差了")
        }

        return uid;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/14 19:08
     * @description ：根据学生uid修改密码 (其一来源：uid来源于token)（前提是已绑定邮箱且验证码已验证成功）
     */
    @Override
    public int editPwdByUid(User user) {
        int i = userMapper.editPwdByUid(user);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_TOKEN); // (401, "服务器开小差了")
        }

        return i;
    }

    /**
     * @author ：Lq
     * @date ：2022/11/14 22:08
     * @description ：根据学生uid、旧密码修改密码并返回新生成的token (其一来源：uid来源于token)
     */
    @Override
    public String editPwdByUidAndOldPassword(Integer uid, String newPassword, String oldPassword) {
        int i = userMapper.editPwdByUidAndOldPassword(uid, newPassword, oldPassword);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_PASSWORD); // (401, "修改密码失败，密码不正确")
        }

        // 到这步修改密码已经成功了
        User user = new User();
        user.setUid(uid);
        user.setPassword(newPassword);

        // 重新生成token并返回
        return tokenUtil.getToken(user);
    }

    /**
     * @author ：Lq
     * @date ：2022/11/16 18:58
     * @description ：根据评论commentId和用户uid，删除对应的评论表
     */
    @Override
    public int delCommentByCommentIdAndUid(Integer commentId, Integer uid) {
        int i = userMapper.delCommentByCommentIdAndUid(commentId, uid);

        if (i == 0) {
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_DELETE_DATA); // (401, "删除失败，服务器开小差了")
        }

        return i;
    }
}
